package com.mrd.gtimp.base.Identifier;


import com.mrd.gtimp.base.entity.SystemValue;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

/**
 * <p> application name: sample <p> copyright: Copyright@2012 明睿达科技有限公司
 */

/**
 * 生成S0001,S0002...这样的主键，用于船舶ID
 *
 * @author qiul
 */
public class SysValueIdGenerator implements IdentifierGenerator, Configurable {

    private static String topLevelQuerySql = null;
    private static String childQuerySql = null;

    @Override
    public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {
        String id = "";
        SystemValue sv = (SystemValue) obj;
        String pid = sv.getParentId();
        try (Connection conn = session.connection(); PreparedStatement statement = conn.prepareStatement(StringUtils.isEmpty(pid) ? topLevelQuerySql : childQuerySql)) {
            if (StringUtils.isEmpty(pid)) {
                ResultSet rs = statement.executeQuery();
                if (rs.next()) {
                   return nextPid(rs.getString(0));
                } else {
                    return "A";
                }
            } else {
                statement.setObject(1, pid);
                ResultSet rs = statement.executeQuery();
                if (rs.next()) {
                    String s = rs.getString(0);
                    if (StringUtils.isEmpty(s)) {
                        return pid + "01";
                    } else {
                        String prefix = s.substring(0, pid.length());
                        int index = Integer.parseInt(s.substring(pid.length()));
                        index++;
                        if (index < 10) {
                            return prefix + "0" + index;
                        } else {
                            return prefix + index;
                        }
                    }
                } else {
                    return pid + "01";
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return id;
    }

    /**
     * 生成下一个pid
     */
    private static String nextPid(String s) {
        // 最初值为'A'
        if (StringUtils.isEmpty(s)) {
            return "A";
        } else {
            boolean allZ = true;
            // 检查是不是都为Z了
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) < 'Z' && s.charAt(i) >= 'A') {
                    allZ = false;
                }
            }
            // 如果所有字符都为Z，则直接进位
            if (allZ) {
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < s.length() + 1; i++) {
                    sb.append("A");
                }
                return sb.toString();
            }
            char[] chars = s.toCharArray();
            chars[chars.length - 1] = (char) (chars[chars.length - 1] + 1);
            // 看最后一个字母是不是大于Z，如果大于则进行进位操作，否则直接返回
            if (chars[chars.length - 1] > 'Z') {
                for (int i = (chars.length - 1); i > 0; i--) {
                    if (chars[i] > 'Z') {
                        chars[i] = 'A';
                        chars[i - 1] = (char) (chars[i - 1] + 1);
                    }
                }
            }
            return new String(chars);
        }
    }


    @Override
    public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
        String table = params.getProperty("target_table");
        String column = params.getProperty("target_column");
        topLevelQuerySql = "select max(" + column + ") max_val from " + table + " where pid is null";
        childQuerySql = "select max(" + column + ") max_val from " + table + " where pid = ?";
    }
}
